﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Lib.Assembly
{
    public class AssemblyResource
    {
        public string AssemblyName { get; private set; }
        public string QualifiedResourcePath { get; private set; }

        public AssemblyResource(string assemblyName, string resPath)
        {
            CheckStringProperty(assemblyName, "AssemblyName");
            CheckStringProperty(resPath, "QualifiedResourcePath");

            AssemblyName = assemblyName;
            QualifiedResourcePath = resPath;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (!obj.GetType().IsAssignableFrom(typeof(AssemblyResource)))
                return false;

            AssemblyResource toCompare = obj as AssemblyResource;
            return this.AssemblyName.Equals(toCompare.AssemblyName) &&
                   this.QualifiedResourcePath.Equals(toCompare.QualifiedResourcePath);
        }

        public override int GetHashCode()
        {
            int hashCode = 13;
            //Computes the hash code for the property PatientBase.Name
            hashCode = GetHashCode(AssemblyName, hashCode, 7);
            //Computes the hash code for the property PatientBase.Firstname, and plus the hash code of the first. 
            hashCode = GetHashCode(QualifiedResourcePath, hashCode, 7);

            return hashCode;
        }

        private void CheckStringProperty(string propertyValue, string propertyName)
        {
            if (string.IsNullOrWhiteSpace(propertyValue))
                throw new AssemblyResourceException(string.Format("The {0} of a AssemblyResource can not be null or empty", propertyName));
        }

        /// <summary>
        /// Computes the hash code of a string using the SHA256 algorithm.
        /// </summary>
        /// <param name="str"></param>
        /// <param name="baseInt"></param>
        /// <param name="stepFactor"></param>
        /// <returns></returns>
        private int GetHashCode(string str, int baseInt, int stepFactor)
        {
            if (str == null) str = string.Empty;
            System.Text.UnicodeEncoding UE = new System.Text.UnicodeEncoding();
            byte[] strBytes = UE.GetBytes(str);
            using (System.Security.Cryptography.SHA256 mySHA256 = System.Security.Cryptography.SHA256Managed.Create())
            {
                int hashCode = baseInt;
                byte[] hashedBytes = mySHA256.ComputeHash(strBytes);
                foreach (byte b in hashedBytes)
                {
                    hashCode += hashCode * stepFactor + (int)b;
                }
                //return hashed.GetHashCode();
                return hashCode;
            }
        }


        private System.Reflection.Assembly _assembly;
        public bool IsValid
        {
            get
            {
                try 
                {
                    if (_assembly == null)
                    {
                        _assembly = System.Reflection.Assembly.Load(AssemblyName);
                    }

                    IEnumerable<string> resNameList = _assembly.GetManifestResourceNames();
                    resNameList.Single(resPath => QualifiedResourcePath == resPath);
                    return true; 
                }
                catch 
                { 
                    return false; 
                }
            }
        }
    }
}
